#include "timer.h"
#include "io.h"
#include "print.h"
#include "interrupt.h"
#include "thread.h" 
#include "debug.h"

#define		IRQ0_FREQUENCY		100
#define		INPUT_FREQUENCY		1193180
#define		COUNTOR0_VALUE		INPUT_FREQUENCY / IRQ0_FREQUENCY
#define 	COUNTOR0_PORT		0x40
#define		COUNTOR0_NO		0
#define		COUNTOR_MODE		2
#define		READ_WRITE_LATCH	3
#define		PIT_CONTROL_PORT	0x43

uint32_t ticks;    //total time

/*set rwl countor_mode countor_value to countor_no*/
static void frequency_set(uint8_t countor_port, \
		uint8_t countor_no, \
		uint8_t rwl, \
		uint8_t countor_mode, \
		uint16_t countor_value) {
	/*write control word to 0x43*/
	outb(PIT_CONTROL_PORT,(uint8_t)(countor_no << 6 | rwl << 4 | countor_mode << 1));
	/*write countor_value low 8 bits*/
	outb(countor_port,(uint8_t)(countor_value));
	/*write countor_value high 8 bits*/
	outb(countor_port,(uint8_t)(countor_value >> 8));
}

/*timer handler function*/
static void intr_timer_handler(void) {
	struct task_struct* cur_thread = running_thread();

	ASSERT(cur_thread->stack_magic == 0x19850125);

	cur_thread->elapsed_ticks++;
	ticks++;

	if(cur_thread->ticks == 0) {
		schedule();
	} else {
		cur_thread->ticks--;
	}
}

/*init PIT8253*/
void timer_init(){
	put_str("timer_init start\n");
	/*set 8253 frequency*/
	frequency_set(COUNTOR0_PORT,COUNTOR0_NO,READ_WRITE_LATCH,COUNTOR_MODE,COUNTOR0_VALUE);
	register_handler(0x20,intr_timer_handler);  //register the timer interrupt function
        put_str("timer_init done\n");
}
